package br.com.eji.drivers;

import java.io.File;
import java.util.Set;
import java.util.Stack;

import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.NoAlertPresentException;
import org.openqa.selenium.firefox.FirefoxDriver;

public class FoxDriver extends FirefoxDriver{
	private enum HandleType {
		WINDOW, IFRAME;
	}

	private class Handle {
		HandleType type;
		String handle;

		public Handle(String handle, HandleType type) {
			this.type = type;
			this.handle = handle;
		}
	}
	
	private static FoxDriver instance;
	private Stack<Handle> windowHandles;
	public boolean isLogged = false;
	
	private FoxDriver() {
		super();
		this.windowHandles = new Stack<Handle>();
		windowHandles
				.push(new Handle(this.getWindowHandle(), HandleType.WINDOW));
	}
	
	public static FoxDriver getInstance() {
		if (instance == null) {
			instance = new FoxDriver();
		}
		return instance;
	}
	
	public void downToWindow(String windowTitle) throws FoxDriverException {
		Set<String> handles = this.getWindowHandles();
		for (String s : handles) {
			this.switchTo().window(s);
			if (this.getTitle() != null && this.getTitle().equals(windowTitle)) {
				windowHandles.push(new Handle(s, HandleType.WINDOW));
				return;
			}
		}
		upWindow(this.windowHandles.pop());
		throw new FoxDriverException("Child window not found!");
	}
	
	public void downToWindowNoTitle(String windowTitle) throws FoxDriverException {
		Set<String> handles = this.getWindowHandles();
		for (String s : handles) {
			this.switchTo().window(s);
			if (this.getTitle().equals(windowTitle)) {
				windowHandles.push(new Handle(s, HandleType.WINDOW));
				return;
			}
		}
		upWindow(this.windowHandles.pop());
		throw new FoxDriverException("Child window not found!");
	}
	
	public void downToIframe(String iframeId) throws FoxDriverException {
		try {
			this.switchTo().frame(this.findElement(By.id(iframeId)));
			this.windowHandles.push(new Handle(iframeId, HandleType.IFRAME));
		} catch (Exception e) {
			throw new FoxDriverException("IFrame not found!");
		}
	}
	
	private void upWindow(Handle h) {
		if (h.type.equals(HandleType.WINDOW)) {
			this.switchTo().window(h.handle);
			this.windowHandles.push(h);
		} else if (h.type.equals(HandleType.IFRAME)) {
			upWindow(this.windowHandles.pop());
			this.switchTo().frame(this.findElement(By.id(h.handle)));
			this.windowHandles.push(h);
		}
	}
	
	public void alertAccept() throws FoxDriverException {
		try {
			Alert alert = this.switchTo().alert();
			alert.accept();
		} catch (NoAlertPresentException ex) {
			throw new FoxDriverException("Alert not found!");
		}
	}
	
	public void upToParent(boolean closeCurrentWindow) {
		if (this.windowHandles.size() > 1) {
			if (closeCurrentWindow
					&& this.windowHandles.peek().type.equals(HandleType.WINDOW)) {
				if (this instanceof JavascriptExecutor) {
					((JavascriptExecutor) this)
							.executeScript("window.onbeforeunload = null;");
				}
				this.close();
			}
			this.windowHandles.pop();
			upWindow(this.windowHandles.pop());
		}
	}
	
	public void upToMainWindow() {
		while (this.windowHandles.size() > 1) {
			this.windowHandles.pop();
		}
		this.switchTo().window(this.windowHandles.peek().handle);
	}
}
